package core

import (
	"fmt"
	"gitee.com/ktark/ktark-framework/ktark-core/function"
	"gitee.com/ktark/ktark-framework/ktark-core/lang"
	"gitee.com/ktark/ktark-framework/ktark-core/util/assert"
)

// ==================
// core-attribute_accessor: 属性访问器
// ==================

// AttributeAccessor 属性访问器
type AttributeAccessor interface {

	// SetAttribute 设置属性
	//
	//	Parameters
	//		name 属性名
	//		value 属性值
	//	Returns
	//	 	bool 是否成功
	SetAttribute(name string, value interface{}) bool

	// GetAttribute 设置属性
	//
	//	Parameters
	//		name 属性名
	//	Returns
	//	 	interface 属性值
	GetAttribute(name string) interface{}

	// RemoveAttribute 移除属性
	//
	//	Parameters
	//		name 属性名
	//	Returns
	//	 	interface 属性值
	RemoveAttribute(name string) interface{}

	// HasAttribute 判断属性是否存在
	//
	//	Parameters
	//		name 属性名
	//	Returns
	//	 	bool 是否存在
	HasAttribute(name string) bool

	// AttributeNames 名称数组
	//	Returns
	//	 	[]string 属性名称切片
	AttributeNames() []string

	// ComputeAttribute 设置属性
	//
	//	Parameters
	//		name 属性名
	//		fun 属性值处理函数
	//	Returns
	//	 	interface 属性值
	ComputeAttribute(name string, fun function.Function[string, lang.Object]) lang.Object
}

// -----------------------AbstractAttributeAccessor-------------------------

// AbstractAttributeAccessor 抽象属性访问器
type AbstractAttributeAccessor struct {
	AttributeAccessor
}

// ComputeAttribute 计算属性。当存在@Parem{name}则返回，不存在则回调@Param{computeFunction},
// 返回的值就调用@Code{core.AttributeAccessor#SetAttribute}
func (receiver *AbstractAttributeAccessor) ComputeAttribute(name string, computeFunction function.Function[string, lang.Object]) lang.Object {
	assert.NotNil(name, "Name must not be null")
	assert.NotNil(computeFunction, "Compute function must not be null")
	value := receiver.GetAttribute(name)
	if value == nil {
		value = computeFunction(name)
		assert.State(value != nil, func() string {
			return fmt.Sprintf("Compute function must not return null for attribute named '%s'", name)
		})
		receiver.SetAttribute(name, value)
	}
	return value
}

// -----------------------AttributeAccessorSupport-------------------------

// AttributeAccessorSupport 属性访问支持。基础@Code{core.AttributeAccessor}实现
type AttributeAccessorSupport struct {
	*AbstractAttributeAccessor
	attributes map[string]interface{}
}

// SetAttribute 设置属性
func (receiver *AttributeAccessorSupport) SetAttribute(name string, value interface{}) bool {
	assert.NotNil(name, "Name must not be null")
	if value != nil {
		receiver.attributes[name] = value
	} else {
		delete(receiver.attributes, name)
	}
	return true
}

// GetAttribute 获取属性
func (receiver *AttributeAccessorSupport) GetAttribute(name string) interface{} {
	assert.NotNil(name, "Name must not be null")
	return receiver.attributes[name]
}

// RemoveAttribute 移除属性
func (receiver *AttributeAccessorSupport) RemoveAttribute(name string) interface{} {
	assert.NotNil(name, "Name must not be null")
	removeVal := receiver.attributes[name]
	delete(receiver.attributes, name)
	return removeVal
}

// HasAttribute 是否有属性
func (receiver *AttributeAccessorSupport) HasAttribute(name string) bool {
	assert.NotNil(name, "Name must not be null")
	_, ok := receiver.attributes[name]
	return ok
}

// AttributeNames 属性名切片
func (receiver *AttributeAccessorSupport) AttributeNames() []string {
	j := 0
	keys := make([]string, len(receiver.attributes))
	for k := range receiver.attributes {
		keys[j] = k
		j++
	}
	return keys
}

// CopyAttributesFrom 从来源@Param{source}拷贝属性
func (receiver *AttributeAccessorSupport) CopyAttributesFrom(source AttributeAccessor) {
	names := source.AttributeNames()
	for i := range names {
		receiver.SetAttribute(names[i], source.GetAttribute(names[i]))
	}
}

// NewAttributeAccessorSupport new AttributeAccessorSupport
func NewAttributeAccessorSupport() *AttributeAccessorSupport {
	absAttrAc := new(AbstractAttributeAccessor)
	support := &AttributeAccessorSupport{AbstractAttributeAccessor: absAttrAc, attributes: make(map[string]interface{}, 8)}
	absAttrAc.AttributeAccessor = support
	return support
}
